# This file is part of The Vu Toolkit.
#
# The Vu Toolkit is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3.0 of the License, or (at your option) any later version.
#
# The Vu Toolkit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with The Vu Toolkit; if not, write to the Free
# Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
# 02111-1307 USA.
#
# Copyright © Zak Fenton 2008
#

module Vu::SVG
	# A transformation matrix. Implemented as an SVG friendly wrapper over
	# Cairo::Matrix.
	class Transformation
		def initialize
			@matrix = Cairo::Matrix.translate(0,0)
		end
		
		# Parse a transformation ("translate(10,10) rotate(-30)", etc.).
		# Many thanks to whoever invented regular expressions.
		#
		# FIXME: multi-argument rotates are certain to break me!
		def self.parse (s)
			# Split it into just the words and numbers
			spl = s.split(/[ ,\(\)]+/)
			t = Transformation.new
			# Recursively parse and apply the transformations
			parse_splitted(spl,t)
			return t
		end
		
		def self.parse_splitted (s,t)
			if s.length > 0
				case s[0]
					when 'translate'
						t.translate!(s[1].to_f,s[2].to_f)
						parse_splitted(s[3, s.length], t)
					when 'rotate'
						t.rotate_deg!(s[1].to_f)
						parse_splitted(s[2, s.length], t)
					else
						throw "Unknown SVG transformation #{s}"
				end		
			end		
		end
	
		# Surely ruby has PI somewhere?
		def self.PI
			3.141
		end
	
		# Rotates by degrees (360 = full circle)
		def rotate_deg! (d)
			rotate_rad!(d*(3.141/180))
		end
		
		# Rotates by radians (2*PI = full circle)
		def rotate_rad! (r)
			@matrix.rotate!(r)
		end
		
		# Translate
		def translate! (x,y)
			@matrix.translate!(x,y)
		end
		
		# Scale
		def scale! (x,y)
			@matrix.scale!(x,y)
		end
		
		# Apply another transformation to this one, modifying this transformation.
		def apply! (t)
			@matrix.multiply!(t.cairo_matrix)
		end
		
		# Apply to a Cairo context
		def apply_to_cairo (cr)
			cr.transform(@matrix)
		end
		
		# Gets the Cairo matrix
		def cairo_matrix
			@matrix
		end
	end
end

